package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.factory.StrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.user.strategy.impl.AlbumStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private StrategyFactory strategyFactory;

    @Override
    public Map<String, Object> wxLogin(String code) {
        //	声明一个map 集合
        Map<String, Object> map = new HashMap<>();
        //	容器自己构建的对象缺少：appid secret
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //	获取到了微信用户对应的微信标识
        String openid = wxMaJscode2SessionResult.getOpenid();
        //	通过这个openid 查询用户信息，如果有对应的信息记录，则说明用户已经注册过; 如果没有，则说明用户未注册过，实现注册功能，并初始化账户金额; 留住用户;
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        //	判断用户信息是否存在
        if (null == userInfo) {
            //	第一次注册;
            //	发送消息实现初始化账户信息；
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("用户" + UUID.randomUUID().toString().replaceAll("-", ""));
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //	添加到表中;
            userInfoMapper.insert(userInfo);
            //	发送一个消息，账户金额初始化;
            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        //	直接存储到缓存，并返回一个token;
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //	缓存key
        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        //	获取到当前服务器的Ip 地址：   userInfo+ip;
        redisTemplate.opsForValue().set(userLoginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        //	存储数据
        map.put("token", token);
        //	返回数据
        return map;
    }

    @Override
    public void updateVipExpireStatus() {
        //  调用mapper 层;
        userInfoMapper.updateVipExpireStatus();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        //        if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
        //            ItemTypeStrategy itemTypeStrategy = new AlbumStrategy();
        //            itemTypeStrategy.savePaidRecord(userPaidRecordVo);
        //        } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
        //
        //        }
        //        int result = itemTypeStrategy.savePaidRecord(userPaidRecordVo);
        ItemTypeStrategy itemTypeStrategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        return itemTypeStrategy.savePaidRecord(userPaidRecordVo);
        //  返回数据
        //  声明一个变量
        //        int result = 0;
        //        //  根据itemType 类型判断;
        //        if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
        //            //  购买了专辑 user_paid_album;
        //            //  查询当前记录表中已有数据;
        //            UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)));
        //            //  判断
        //            if (null != userPaidAlbum) {
        //                //  没有插入数据
        //                return result;
        //            }
        //            //  创建一个对象
        //            userPaidAlbum = new UserPaidAlbum();
        //            //  赋值;
        //            userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
        //            userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
        //            userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
        //            //  保存数据;
        //            return result += userPaidAlbumMapper.insert(userPaidAlbum);
        //        } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
        //            //  购买声音user_paid_track;
        //            //  防止购买重复的声音;
        //            //  购买的声音Id;
        //            List<Long> itemIdList = userPaidRecordVo.getItemIdList();
        //            //  根据声音Id获取声音对象;
        //            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
        //            Assert.notNull(trackInfoResult, "查询声音失败！");
        //            TrackInfo trackInfo = trackInfoResult.getData();
        //            Assert.notNull(trackInfo, "查询声音失败！");
        //            //  查询当前用户是否购买过声音; select * from user_paid_track where user_id = 30 and track_id in (1,2,3);
        //            //  一样的就不需要插入数据; 可能涉及到退款；否则就插入数据！
        //            List<Long> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userPaidRecordVo.getUserId()).in(UserPaidTrack::getTrackId, itemIdList)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //            //  循环遍历;
        //            for (Long trackId : itemIdList) {
        //                if (userPaidTrackList.contains(trackId)) {
        //                    //  退款; sendMsg();
        //                    log.warn("退款:" + trackId);
        //                } else {
        //                    //  插入数据；
        //                    UserPaidTrack userPaidTrack = new UserPaidTrack();
        //                    userPaidTrack.setUserId(userPaidRecordVo.getUserId());
        //                    userPaidTrack.setTrackId(trackId);
        //                    userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
        //                    //  获取专辑Id;
        //                    userPaidTrack.setAlbumId(trackInfo.getAlbumId());
        //                    //  保存数据;
        //                    result += userPaidTrackMapper.insert(userPaidTrack);
        //                }
        //            }
        //            return result;
        //        } else {
        //            //  购买vip; user_vip_service; user_info;
        //            //  考虑购买时长;续期; user_vip_service.id;
        //            Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
        //            //  获取购买时间;
        //            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
        //            Integer serviceMonth = vipServiceConfig.getServiceMonth();
        //            UserVipService userVipService = new UserVipService();
        //            //  续期的条件; 现在是未过期的vip!
        //            //  获取信息;
        //            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
        //            Date vipExpireTime = new Date();
        //            //  是未过期的vip 属于续期;
        //            if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())) {
        //                //  续期; 在原有过期时间基础上+现在购买时间;
        //                vipExpireTime = userInfo.getVipExpireTime();
        //                //  日期计算; jdk8有自带的工具类;
        //                LocalDateTime localDateTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth);
        ////                localDateTime.plusMonths(serviceMonth);
        //                //  设置过期时间;
        //                //  userVipService.setExpireTime(localDateTime.toDate());
        //                vipExpireTime = localDateTime.toDate();
        //            } else {
        //                //  当前系统时间+购买时间;
        ////                userVipService.setExpireTime(new LocalDateTime(userVipService).plusMonths(serviceMonth).toDate());
        //                vipExpireTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth).toDate();
        //            }
        //            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userVipService.setUserId(userPaidRecordVo.getUserId());
        //            userVipService.setStartTime(new Date());
        //            //  设置过期时间
        //            userVipService.setExpireTime(vipExpireTime);
        //            //  保存数据;
        //            result += userVipServiceMapper.insert(userVipService);
        //            //  抛出异常！
        //            //  int i = 1/0;
        //            //  更新user_info;
        //            //  不管你是是不是续期，还是购买
        //            userInfo.setIsVip(1);
        //            userInfo.setVipExpireTime(vipExpireTime);
        //            result += userInfoMapper.updateById(userInfo);
        //        }
        //        //  返回数据;
        //        return result;
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //  select * from user_paid_track where user_id = 30 and album_id = 391;
        return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userId) {
        //	查询表中是否有记录
        System.out.println("album:\t" + userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId)));
        return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
    }

    /**
     * 判断用户是否购买了声音
     *
     * @param albumId     专辑Id
     * @param trackIdList 付费声音Id 列表; 6-25;
     * @param userId      用户Id
     * @return
     */
    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
        //	创建map 集合
        Map<Long, Integer> map = new HashMap<>();
        //	判断用户是否购买专辑： user_paid_album;
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        //	判断
        if (null != userPaidAlbum) {
            //	这个用户购买过专辑 map.put(trackId,1); map.put(trackId,0); 1:表示已经购买; 0:表示未购买 setIsShowPaidMark(true);
            return trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
        } else {
            //	判断用户是否购买声音： user_paid_track;
            //	构建查询条件;
            LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList).eq(UserPaidTrack::getAlbumId, albumId);
            //	查询到的结果是：这个用户购买过哪些声音 userPaidTrackList 这个集合可能为空：说明用户未购买过任何一条声音;
            //	19,20;
            List<Long> userPaidTrackIdList = userPaidTrackMapper.selectList(wrapper).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            //	List<Long> userPaidTrackIdList;
            //	判断：
            for (Long trackId : trackIdList) {
                //	判断购买声音Id 的集合中是否包含付费声音Id
                if (userPaidTrackIdList.contains(trackId)) {
                    //	购买过
                    map.put(trackId, 1);
                } else {
                    //	未购买过
                    map.put(trackId, 0);
                }
            }
        }
        //	返回集合;
        return map;
    }

    @Override
    public void updateUserInfo(UserInfoVo userInfoVo, Long userId) {
        //	创建对象
        UserInfo userInfo = new UserInfo();
        //	属性拷贝：
        BeanUtils.copyProperties(userInfoVo, userInfo);
        userInfo.setId(userId);
        //	更新用户信息
        userInfoMapper.updateById(userInfo);
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //	查询数据
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝：
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        //	返回数据
        return userInfoVo;
    }
}
